from datetime import datetime
import tkinter as tk
from tkinter import ttk, filedialog, messagebox
from openpyxl import load_workbook
import pandas as pd
import os
import json
import sys


def load_config():
    try:
        # 先尝试从打包资源加载默认配置
        default_config_path = resource_path("config.json")
        if os.path.exists(default_config_path):
            with open(default_config_path, 'r', encoding='utf-8') as f:
                default_config = json.load(f)

        # 如果当前目录配置文件不存在，则创建默认配置
        if not os.path.exists(CONFIG_FILE) and 'default_config' in locals():
            with open(CONFIG_FILE, 'w', encoding='utf-8') as f:
                json.dump(default_config, f, ensure_ascii=False, indent=2)

        # 加载用户配置
        if os.path.exists(CONFIG_FILE):
            with open(CONFIG_FILE, 'r', encoding='utf-8') as f:
                return json.load(f)

    except Exception as e:
        messagebox.showerror("配置错误", f"加载配置文件失败：{str(e)}")
    return {}


def resource_path(relative_path):
    # 获取打包后资源的绝对路径，支持子目录
    base_path = sys._MEIPASS if hasattr(sys, '_MEIPASS') else os.path.abspath(".")
    return os.path.join(base_path, *relative_path.split('/'))


def select_file(entry):
    path = filedialog.askopenfilename(filetypes=[('Excel文件', '*.xlsx'), ('Excel 97-2003', '*.xls')])
    if path:
        entry.delete(0, tk.END)
        entry.insert(0, path)


CONFIG_FILE = os.path.join(os.getcwd(), "config.json")  # 始终使用当前工作目录


def download_template():
    try:
        # 获取桌面路径（跨平台）
        desktop = os.path.join(os.path.expanduser('~'), 'Desktop')
        dest_path = os.path.join(desktop, "数据表模板%s.xlsx" % datetime.now().strftime("%m%d%H%M"))
        source_path = resource_path("public/数据模板表.xlsx")  # 统一使用新路径格式
        if not os.path.exists(source_path):
            raise FileNotFoundError(f"模板文件路径不存在: {source_path}")
        # 复制文件
        import shutil
        shutil.copy(source_path, dest_path)
        messagebox.showinfo("操作成功",
                            f"模板文件已保存至桌面：\n{dest_path}")
    except Exception as e:
        messagebox.showerror("操作失败", f"错误原因：{str(e)}")


MATERIAL_ID = '{{materialId}}'
TIPS_DETAILS = f"商品素材ID可用变量表示：{MATERIAL_ID}"
TIPS_NOT_REQUIRED = f"非必填"


def clear_placeholder1(event):
    widget = event.widget
    if widget.get() == TIPS_NOT_REQUIRED:
        widget.delete(0, tk.END)
        widget.config(foreground='black')


def clear_placeholder2(event):
    # 清除提示词
    widget = event.widget
    if widget.get("1.0", "end-1c") == TIPS_DETAILS:
        widget.delete("1.0", tk.END)
        widget.config(fg='black')


def set_placeholder1(event):
    widget = event.widget
    if not widget.get().strip():
        widget.insert(0, TIPS_NOT_REQUIRED)
        widget.config(foreground='grey')


def set_placeholder2(event):
    # 设置提示词
    widget = event.widget
    if not widget.get("1.0", "end-1c").strip():
        widget.insert(tk.END, TIPS_DETAILS)
        widget.config(fg='grey')


TEXT = "{{text}}"


class TemuDogeApp:
    def __init__(self, master):
        self.master = master
        # 设置窗口属性
        master.geometry(self.get_center_position(435, 720))  # 设置初始窗口尺寸
        master.resizable(False, False)  # 禁用窗口缩放
        # 创建菜单栏
        menu_bar = tk.Menu(master)

        # 帮助菜单
        menu_bar.add_command(label="帮助", command=show_help)
        menu_bar.add_command(label="关于", command=show_about)

        master.config(menu=menu_bar)
        # 加载配置文件
        self.config = load_config()

        # 输入参数框架
        input_frame = ttk.Frame(master, padding="10")
        input_frame.grid(row=0, column=0, sticky=(tk.W, tk.E))

        # 标题输入
        ttk.Label(input_frame, text='中文标题:').grid(row=0, column=0, sticky=tk.W, pady=2)
        self.title_cn = ttk.Entry(input_frame, width=50)
        self.title_cn.insert(0, self.config.get("title_cn", ""))
        self.title_cn.grid(row=0, column=1, padx=(0, 10), pady=2, sticky=tk.W)

        ttk.Label(input_frame, text='英文标题:').grid(row=1, column=0, sticky=tk.W, pady=2)
        self.title_en = ttk.Entry(input_frame, width=50)
        self.title_en.insert(0, self.config.get("title_en", ""))
        self.title_en.grid(row=1, column=1, padx=(0, 10), pady=2, sticky=tk.W)

        # 标题拼接
        self.title_concat_var = tk.StringVar(value=self.config.get("title_concat", "不拼接"))
        ttk.Label(input_frame, text='标题拼接:').grid(row=2, column=0, sticky=tk.W)
        concat_frame = ttk.Frame(input_frame)
        concat_frame.grid(row=2, column=1, sticky=tk.W)

        concat_options = [
            ("素材名称", "素材名称"),
            ("素材ID", "素材ID"),
            ("不拼接", "不拼接")
        ]
        for text, value in concat_options:
            ttk.Radiobutton(concat_frame, text=text, variable=self.title_concat_var,
                            value=value).pack(side=tk.LEFT, padx=5)

        # 颜色单选
        self.color_var = tk.StringVar(value=self.config.get("color", "白色"))
        ttk.Label(input_frame, text='颜色选择:').grid(row=3, column=0, sticky=tk.W)
        # 新增的框架容器
        color_frame = ttk.Frame(input_frame)
        color_frame.grid(row=3, column=1, sticky=tk.W)
        # 将单选按钮放入框架并水平排列
        ttk.Radiobutton(color_frame, text="白色", variable=self.color_var, value="白色").pack(side=tk.LEFT, padx=5)
        ttk.Radiobutton(color_frame, text="黑色", variable=self.color_var, value="黑色").pack(side=tk.LEFT, padx=5)
        # 默认库存
        ttk.Label(input_frame, text='默认库存:').grid(row=4, column=0, sticky=tk.W, pady=2)
        self.default_stock = ttk.Entry(input_frame, width=50)
        self.default_stock.insert(0, self.config.get("default_stock", "10000"))  # 设置默认值
        self.default_stock.grid(row=4, column=1, padx=(0, 10), pady=2, sticky=tk.W)
        # 参考链接
        ttk.Label(input_frame, text='参考链接:').grid(row=5, column=0, sticky=tk.W, pady=2)
        self.reference_link = ttk.Entry(input_frame, width=50)
        self.reference_link.insert(0, self.config.get("reference_link", ""))
        # 初始化占位符状态
        if not self.reference_link.get():  # 只有配置为空时才显示提示
            self.reference_link.insert(0, TIPS_NOT_REQUIRED)
            self.reference_link.config(foreground='grey')
        self.reference_link.grid(row=5, column=1, padx=(0, 10), pady=2, sticky=tk.W)
        # 绑定事件
        self.reference_link.bind("<FocusIn>", clear_placeholder1)
        self.reference_link.bind("<FocusOut>", set_placeholder1)
        # 白色素材ID组
        white_frame = ttk.LabelFrame(input_frame, text="【白色】轮播图素材ID", padding=5)
        white_frame.grid(row=6, column=0, columnspan=2, sticky=tk.EW, pady=5)
        self.white_ids = []
        for i in range(4):
            row_idx = i // 2  # 每两个ID一行
            col_idx = (i % 2) * 2  # 0, 2列交替

            ttk.Label(white_frame, text=f'ID {i + 1}:').grid(row=row_idx, column=col_idx, padx=(10, 0))
            entry = ttk.Entry(white_frame, width=16)
            entry.insert(0, self.config.get(f"white_id_{i + 1}", ""))
            entry.grid(row=row_idx, column=col_idx + 1, padx=(5, 15), pady=3)
            self.white_ids.append(entry)

        # 黑色素材ID组
        black_frame = ttk.LabelFrame(input_frame, text="【黑色】轮播图素材ID", padding=5)
        black_frame.grid(row=7, column=0, columnspan=2, sticky=tk.EW)
        self.black_ids = []
        for i in range(4):
            row_idx = i // 2
            col_idx = (i % 2) * 2

            ttk.Label(black_frame, text=f'ID {i + 1}:').grid(row=row_idx, column=col_idx, padx=(10, 0))
            entry = ttk.Entry(black_frame, width=16)
            entry.insert(0, self.config.get(f"black_id_{i + 1}", ""))
            entry.grid(row=row_idx, column=col_idx + 1, padx=(5, 15), pady=3)
            self.black_ids.append(entry)

        # 白色图文详情
        white_details_frame = ttk.LabelFrame(input_frame, text="【白色】图文详情", padding=5)
        white_details_frame.grid(row=8, column=0, columnspan=2, sticky=tk.EW, pady=5)
        self.white_details_text = tk.Text(white_details_frame, width=48, height=3, wrap=tk.WORD, fg='grey')
        self.white_details_text.pack(padx=5, pady=3)
        self.white_details_text.insert(tk.END, TIPS_DETAILS)
        self.white_details_text.bind("<FocusIn>", clear_placeholder2)
        self.white_details_text.bind("<FocusOut>", set_placeholder2)
        # 如果有保存的配置值，则替换提示词
        if 'white_details' in self.config and self.config["white_details"]:
            self.white_details_text.delete("1.0", tk.END)
            self.white_details_text.insert(tk.END, self.config["white_details"])
            self.white_details_text.config(fg='black')

        # 黑色图文详情
        black_details_frame = ttk.LabelFrame(input_frame, text="【黑色】图文详情", padding=5)
        black_details_frame.grid(row=9, column=0, columnspan=2, sticky=tk.EW)
        self.black_details_text = tk.Text(black_details_frame, width=48, height=3, wrap=tk.WORD, fg='grey')
        self.black_details_text.pack(padx=5, pady=3)
        self.black_details_text.insert(tk.END, TIPS_DETAILS)  # 默认提示词
        self.black_details_text.bind("<FocusIn>", clear_placeholder2)
        self.black_details_text.bind("<FocusOut>", set_placeholder2)
        # 如果有保存的配置值，则替换提示词
        if 'black_details' in self.config and self.config["black_details"]:
            self.black_details_text.delete("1.0", tk.END)
            self.black_details_text.insert(tk.END, self.config["black_details"])
            self.black_details_text.config(fg='black')

        # 文件选择框架
        file_frame = ttk.Frame(master, padding="10")
        file_frame.grid(row=1, column=0, sticky=(tk.W, tk.E))

        # 表1选择
        self.table1_entry = ttk.Entry(file_frame, width=44)
        self.table1_entry.grid(row=0, column=0, padx=5)
        ttk.Button(file_frame, text="选择素材表", command=lambda: select_file(self.table1_entry)).grid(row=0, column=1)
        if 'table1_path' in self.config:
            self.table1_entry.insert(0, self.config.get("table1_path"))

        # 表2选择
        self.table2_entry = ttk.Entry(file_frame, width=44)
        self.table2_entry.grid(row=1, column=0, padx=5)
        ttk.Button(file_frame, text="选择模板表", command=lambda: select_file(self.table2_entry)).grid(row=1, column=1)
        if 'table2_path' in self.config:
            self.table2_entry.insert(0, self.config.get("table2_path"))

        # 自定义数据选择
        self.custom_entry = ttk.Entry(file_frame, width=44)
        self.custom_entry.grid(row=2, column=0, padx=5)
        ttk.Button(file_frame, text="自定义数据", command=lambda: select_file(self.custom_entry)).grid(row=2, column=1)
        if 'custom_data_path' in self.config:
            self.custom_entry.insert(0, self.config.get("custom_data_path"))

        # 操作按钮框架
        btn_frame = ttk.Frame(master)
        btn_frame.grid(row=2, column=0, pady=10)
        self.generate_btn = ttk.Button(btn_frame, text="生成模板", command=self.generate_table)
        self.generate_btn.pack(side=tk.LEFT, padx=5)

        ttk.Button(btn_frame, text="保存配置", command=self.update_config).pack(side=tk.LEFT, padx=5)
        # 下载模板按钮
        ttk.Button(btn_frame, text="下载数据模板", command=download_template).pack(side=tk.LEFT, padx=5)
        # 状态提示
        self.status_var = tk.StringVar()
        self.status_label = ttk.Label(master, textvariable=self.status_var, foreground="blue")
        self.status_label.grid(row=3, column=0)

    def save_config(self):
        # 保存配置文件
        try:
            with open(CONFIG_FILE, 'w', encoding='utf-8') as f:
                json.dump(self.config, f, ensure_ascii=False, indent=2)
            return True
        except Exception as e:
            messagebox.showerror("配置错误", f"保存配置失败：{str(e)}")
            return False

    def update_config(self):
        # 获取内容时过滤提示词
        white_details = self.white_details_text.get("1.0", tk.END).strip()
        if white_details == TIPS_DETAILS:
            white_details = ""

        black_details = self.black_details_text.get("1.0", tk.END).strip()
        if black_details == TIPS_DETAILS:
            black_details = ""
        reference_link = self.reference_link.get().strip()
        if reference_link == TIPS_NOT_REQUIRED:
            reference_link = ""
        self.config.update({
            "title_cn": self.title_cn.get(),
            "title_en": self.title_en.get(),
            "title_concat": self.title_concat_var.get(),
            "color": self.color_var.get(),
            "default_stock": self.default_stock.get(),
            "reference_link": reference_link,
            "table1_path": self.table1_entry.get(),
            "table2_path": self.table2_entry.get(),
            "custom_data_path": self.custom_entry.get(),
            "white_details": white_details,
            "black_details": black_details,
            **{f"white_id_{i + 1}": entry.get() for i, entry in enumerate(self.white_ids)},
            **{f"black_id_{i + 1}": entry.get() for i, entry in enumerate(self.black_ids)}
        })
        if self.save_config():
            messagebox.showinfo("提示", "配置已更新")

    def generate_table(self):
        try:
            # 获取颜色对应的素材ID
            color = self.color_var.get()
            concat_mode = self.title_concat_var.get()
            material_ids = [
                entry.get() for entry in
                (self.white_ids if color == "白色" else self.black_ids)
            ]
            details = self.white_details_text if color == "白色" else self.black_details_text
            details_content = details.get("1.0", tk.END).strip()
            # 验证库存
            try:
                stock = int(self.default_stock.get())
            except ValueError:
                messagebox.showerror("错误", "库存必须为整数")
                return
            if stock < 3:
                messagebox.showerror("错误", "库存大于2")
                return
            # 验证输入
            required_fields = [
                self.title_cn.get(),
                self.title_en.get(),
                stock,
                *material_ids,
                self.table1_entry.get(),
                self.table2_entry.get(),
                self.custom_entry.get(),
                details_content
            ]

            if not all(required_fields):
                raise ValueError("所有字段必须填写")

            # 禁用按钮并显示提示
            self.generate_btn.config(state=tk.DISABLED)
            self.status_var.set("正在生成模板，请稍候...")
            self.master.update()  # 强制刷新界面
            # 读取数据
            df1 = pd.read_excel(self.table1_entry.get())
            df1['素材名称'] = df1['素材名称'].astype(str)  # 将素材名称列转换为字符串类型
            custom_data = {}
            if self.custom_entry.get():
                try:
                    df_custom = pd.read_excel(self.custom_entry.get())
                    df_custom['素材名称'] = df_custom['素材名称'].astype(str)  # 将素材名称列转换为字符串类型
                    custom_data = df_custom.set_index('素材名称').to_dict(orient='index')
                except Exception as err:
                    messagebox.showwarning("警告", f"自定义数据加载失败：{str(err)}")
            # 读取模板文件（保留所有格式和公式）
            wb = load_workbook(filename=self.table2_entry.get())
            sheet = wb['模版']  # 获取指定工作表
            start_row = 5
            # 循环素材表
            for index, row in df1.iterrows():
                start_row = start_row + 1
                material_name = row["素材名称"]
                material_id = row["素材ID"]
                row_num = str(start_row)
                # 根据拼接模式处理标题
                if concat_mode == "素材名称":
                    final_title_cn = f"{self.title_cn.get()}{material_name}"
                    final_title_en = f"{self.title_en.get()}{material_name}"
                elif concat_mode == "素材ID":
                    final_title_cn = f"{self.title_cn.get()}{material_id}"
                    final_title_en = f"{self.title_en.get()}{material_id}"
                else:
                    final_title_cn = self.title_cn.get()
                    final_title_en = self.title_en.get()
                # 获取自定义数据
                custom = custom_data.get(material_name, {})
                custom_title_cn = custom.get('中文标题')
                final_title_cn = custom_title_cn if not pd.isna(custom_title_cn) else final_title_cn
                custom_title_en = custom.get('英文标题')
                final_title_en = custom_title_en if not pd.isna(custom_title_en) else final_title_en
                # 将中文符号替换为英文字符
                final_title_en = (final_title_en
                                  .replace("，", ",")
                                  .replace("。", ".")
                                  .replace("“", "\"")
                                  .replace("”", "\"")
                                  .replace("；", ";")
                                  .replace("？", "?")
                                  .replace("！", "!"))
                # 为标题中的自定义变量赋值
                final_title_cn = final_title_cn.replace(TEXT, custom.get('自定义文本') or "")
                final_title_en = final_title_en.replace(TEXT, custom.get('自定义文本') or "")
                pattern_style = custom.get('图案风格')
                if pd.isna(pattern_style) or not pattern_style:
                    pattern_style = '几何图案'
                # SPU
                sheet['A' + row_num] = 'spu'
                sheet['B' + row_num] = material_id
                sheet['C' + row_num] = final_title_cn
                sheet['D' + row_num] = final_title_en
                sheet['E' + row_num] = '美国'
                sheet['G' + row_num] = '棉'
                sheet['H' + row_num] = '棉'
                sheet['I' + row_num] = '100%'
                sheet['R' + row_num] = pattern_style
                sheet['S' + row_num] = '无'
                sheet['T' + row_num] = '圆领'
                sheet['U' + row_num] = '休闲'
                sheet['V' + row_num] = '可机洗且不可干洗'
                sheet['W' + row_num] = '微弹'
                sheet['X' + row_num] = '成人'
                sheet['Y' + row_num] = '四季'
                sheet['Z' + row_num] = '否'
                sheet['AA' + row_num] = '宽松'
                sheet['AB' + row_num] = '针织(含钩织、毛织面料)'
                sheet['AC' + row_num] = '定位印花'
                sheet['AD' + row_num] = '光面'
                sheet['AE' + row_num] = 180
                sheet['AF' + row_num] = 'g/㎡'
                sheet['AG' + row_num] = '无里料/无内衬'
                sheet['AU' + row_num] = '常规袖/直筒袖'
                sheet['AV' + row_num] = '短袖'
                sheet['AX' + row_num] = '休闲外出'
                sheet['AY' + row_num] = '日常和休闲'
                sheet['BX' + row_num] = 'Cuthbert'
                sheet['BY' + row_num] = 'M'
                sheet['BZ' + row_num] = '合身'
                sheet['DJ' + row_num] = details_content.replace(MATERIAL_ID,
                                                                str(material_id)) if details_content != TIPS_DETAILS else ""
                # SKU
                size = ["S", "M", "L", "XL", "XXL", "XXXL"]
                shoulder = ['50.5', '52', '53.8', '55.6', '57.4', '59.2']
                chest = ['108', '112', '117', '122', '127', '132']
                clothes = ['70', '72', '74', '76', '78', '80']
                outside_sleeve = ['22.5', '23', '23.5', '24', '24.5', '25']
                for i in range(6):
                    start_row = start_row + 1
                    row_num = str(start_row)
                    sheet['A' + row_num] = 'sku'
                    sheet['B' + row_num] = material_id
                    sheet['BN' + row_num] = material_id
                    sheet['BO' + row_num] = color
                    sheet['BP' + row_num] = '尺码'
                    sheet['BQ' + row_num] = '欧美尺码'
                    sheet['BR' + row_num] = '欧美尺码常规'
                    sheet['BS' + row_num] = size[i]
                    sheet['BT' + row_num] = shoulder[i]
                    sheet['BU' + row_num] = chest[i]
                    sheet['BV' + row_num] = clothes[i]
                    sheet['BW' + row_num] = outside_sleeve[i]
                    sheet[
                        'CA' + row_num] = self.reference_link.get() if self.reference_link.get() != TIPS_NOT_REQUIRED else ""
                    sheet['CB' + row_num] = 100
                    sheet['CC' + row_num] = 'CNY'
                    sheet['CD' + row_num] = 'Devil Inc'
                    sheet['CE' + row_num] = stock
                    sheet['CF' + row_num] = '单品'
                    sheet['CG' + row_num] = 1
                    sheet['CH' + row_num] = '件'
                    sheet['CJ' + row_num] = 15.99
                    sheet['CV' + row_num] = 31
                    sheet['CW' + row_num] = 25
                    sheet['CX' + row_num] = 1
                    sheet['CY' + row_num] = 250
                    sheet['CZ' + row_num] = material_id
                    sheet['DA' + row_num] = material_ids[0]
                    sheet['DB' + row_num] = material_ids[1]
                    sheet['DC' + row_num] = material_ids[2]
                    sheet['DD' + row_num] = material_ids[3]

            # 生成输出路径
            output_dir = os.path.dirname(self.table2_entry.get())
            output_path = os.path.join(output_dir, "商品上传表%s.xlsx" % datetime.now().strftime("%m%d%H%M"))

            # 保存结果
            wb.save(output_path)
            messagebox.showinfo("成功", f"商品上传表已生成：{output_path}")

        except Exception as e:
            messagebox.showerror("错误", str(e))
        finally:
            # 恢复按钮状态
            self.generate_btn.config(state=tk.NORMAL)
            self.status_var.set("")

    def get_center_position(self, width, height):
        # 计算居中位置
        screen_width = self.master.winfo_screenwidth()
        screen_height = self.master.winfo_screenheight()
        x = (screen_width - width) // 2
        y = (screen_height - height) // 2
        return f"{width}x{height}+{x}+{y}"


def show_help():
    help_content = f"""使用说明：
1. 中英文标题为默认标题，并且标题拼接仅对其生效。如果在【自定义数据】中有标题信息则会覆盖默认标题。
2. 全部标题都支持变量{TEXT}，在【自定义数据表->自定义文本列】中填入变量值。
3. 素材ID在TEMU网站/素材中心/查看。
4. 图文详情支持变量{MATERIAL_ID}，该ID为素材表中的素材ID。
5. 素材表：TEMU网站/素材中心/勾选素材后导出。
6. 模板表：TEMU网站/商品列表/批量导入商品/下载导入模板。
7. 自定义数据：本程序底部按钮【下载数据模板】。"""
    messagebox.showinfo("帮助文档", help_content)


def show_about():
    about_content = f"""Temu Doge 拼多多效率部
版本号：{version}
开发者：白墨
邮箱：whitehw@foxmail.com （合作/帮助/反馈）
更新日志：
2025.05.03  v{version}
1. 新增：数据模板表新增【自定义文本】并为图案风格添加数据验证
2. 删除：前后缀拼接功能
3. 新增：标题支持自定义变量，变量名：{TEXT}
4. 修复：图文详情丢失
2025.04.28  v1.3.0
1. 新增：模板增加【参考链接】
2. 新增：前后缀拼接功能
3. 修复：标题为空时报错
4. 修复：素材名称纯数字时无法找到
"""
    messagebox.showinfo("关于我们", about_content)


version = "1.4.0"

if __name__ == "__main__":
    root = tk.Tk()
    # 设置窗口图标
    try:
        root.iconbitmap(resource_path('public/logo.ico'))
    except Exception as e:
        print("图标加载失败:", str(e))
    root.title("Temu Doge v" + version)
    app = TemuDogeApp(root)
    root.mainloop()
# pyinstaller --onefile --windowed --name "TemuDoge v1.4.0" --icon=public\logo.ico --add-data "config.json;." --add-data "public\logo.ico;public" --add-data "public\数据模板表.xlsx;public" main.py
